package com.xindacloud.sms.portal.component;


import com.xindacloud.sms.portal.config.QueueNames;
import com.xindacloud.sms.portal.dto.SqsSubmitMessageParamDTO;
import com.xindacloud.sms.portal.dto.SubmitMessageDTO;
import com.xindacloud.sms.portal.entity.SmsSubmissionRecord;
import com.xindacloud.sms.portal.entity.SmsTaskTotal;
import com.xindacloud.sms.portal.exchange.ExchangeAction;
import com.xindacloud.sms.portal.exchange.ExchangeMessage;
import com.xindacloud.sms.portal.service.ISmsSubmissionRecordService;
import com.xindacloud.sms.portal.service.ISmsTaskTotalService;
import com.xindacloud.sms.portal.service.ISmsUserService;
import com.xindacloud.sms.portal.utils.CommonUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Component
public class SendNotifyMessageComponent {

    private final ISmsSubmissionRecordService smsSubmissionRecordService;
    private final ISmsUserService smsUserService;
    private final ISmsTaskTotalService taskTotalService;

    private final QueueMessagingTemplate messagingTemplate;
    private final QueueNames queueNames;

    @Autowired
    public SendNotifyMessageComponent(ISmsSubmissionRecordService smsSubmissionRecordService,
                                      ISmsUserService smsUserService, ISmsTaskTotalService taskTotalService,
                                      QueueMessagingTemplate messagingTemplate, QueueNames queueNames) {
        this.smsSubmissionRecordService = smsSubmissionRecordService;
        this.smsUserService = smsUserService;
        this.taskTotalService = taskTotalService;
        this.messagingTemplate = messagingTemplate;
        this.queueNames = queueNames;
    }


    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> sendNotifyMessage(SubmitMessageDTO submitMessageParamDTO, String username, String password) {

        Map<String, Object> resultMap = new HashMap<>();

        final String encoding = CommonUtils.isUnicode(submitMessageParamDTO.getMessageBody()) ? "UNICODE" : "GSM";
        final Integer messageCount = CommonUtils.calcMessageCount(submitMessageParamDTO.getMessageBody());
        submitMessageParamDTO.setMessageCount(messageCount);
        submitMessageParamDTO.setEncoding(encoding);

        final List<String> recipientList = new ArrayList<>(new HashSet<>(submitMessageParamDTO.getRecipientList()));
        final int recipientCount = recipientList.size();
        final String taskId = taskTotalService.saveSmsTaskTotal(SmsTaskTotal.builder()
                .pendingCount(recipientCount)
                .recipientCount(recipientCount)
                .build())
                .getTaskId();

        final Integer userId = smsUserService.queryUserInfoFor(username, password).getUserId();
        int default_record = 1000;
        int batchCount = recipientCount / default_record + (recipientCount % default_record == 0 ? 0 : 1);
        for (int i = 1; i <= batchCount; i++) {
            SqsSubmitMessageParamDTO sqsMsgDTO = new SqsSubmitMessageParamDTO();
            BeanUtils.copyProperties(submitMessageParamDTO, sqsMsgDTO);
            sqsMsgDTO.setUserId(userId);
            sqsMsgDTO.setTaskId(taskId);
            List<String> subRecipientList;
            if (batchCount == i) {
                subRecipientList = recipientList.subList((i - 1) * default_record, recipientCount);
            } else {
                subRecipientList = recipientList.subList((i - 1) * default_record, default_record * (i));
            }

            sqsMsgDTO.setRecipientList(subRecipientList);

            List<SmsSubmissionRecord> submissionRecordList = new ArrayList<>();
            for (String recipient : subRecipientList) {
                final SmsSubmissionRecord submissionRecord = SmsSubmissionRecord.builder()
                        .taskId(taskId)
                        .finalStatus("pending")
                        .sendTo(recipient)
                        .sendFrom(sqsMsgDTO.getSender())
                        .submitStatusCode(0)
                        .messageBody(sqsMsgDTO.getMessageBody())
                        .encoding(sqsMsgDTO.getEncoding())
                        .messageCount(sqsMsgDTO.getMessageCount())
                        .projectId(CommonUtils.buildRandomUUID())
                        .userId(userId)
                        .smsType(sqsMsgDTO.getSmsType())
                        .actionType("SMS")
                        .requestType("HTTP POST")
                        .sign(sqsMsgDTO.getSign())
                        .language(sqsMsgDTO.getLanguage())
                        .cbkUrl(sqsMsgDTO.getCbkUrl())
                        .extend(sqsMsgDTO.getExtend())
                        .build();
                if (Objects.isNull(smsSubmissionRecordService.querySmsSubmissionRecord(submissionRecord))) {
                    submissionRecordList.add(submissionRecord);
                }
            }
            smsSubmissionRecordService.insertBatch(submissionRecordList);

            messagingTemplate.convertAndSend(queueNames.getSubmitSmsQueue(),
                    ExchangeMessage.builder()
                            .action(ExchangeAction.SUBMIT_SMS_ACTION)
                            .data(sqsMsgDTO)
                            .build());
        }
        resultMap.put("messageCount", messageCount);
        resultMap.put("messageId", taskId);

        return resultMap;
    }
}
